package Dag

import (
	"cmp"
	"encoding/json"
	"fmt"
	"maps"
	"os"
	"slices"
	"strings"
)

type DagParams struct {
	letterList map[string][][]interface{}
	letter     map[string][][]interface{}
}

func readFile(filename string, any interface{}) {
	file, err := os.ReadFile(filename)

	if err != nil {
		fmt.Println(err)
		return
	}
	err = json.Unmarshal(file, any)
	if err != nil {
		fmt.Println(err)
		return
	}
}

func DagParamsInit() *DagParams {
	var d DagParams
	d.letterList = make(map[string][][]interface{})
	d.letter = make(map[string][][]interface{})
	// 获取所在目录

	readFile("./dag_char.json", &d.letter)
	readFile("./dag_phrase.json", &d.letterList)
	return &d
}

func (d *DagParams) GetPhrase(pyList []string, num int) (strList [][]interface{}) {
	// ''' pinyin_list是拼音组成的list，例如['yi', 'ge'] '''
	if len(pyList) == 0 {
		return
	}
	data := make(map[string][][]interface{})
	if len(pyList) == 1 {
		data = d.letter
	} else {
		data = d.letterList
	}
	pinyin := strings.Join(pyList, ",")
	if _, has := data[pinyin]; !has {
		list := strings.Split(pinyin, ",")
		if len(list) > 1 {
			var retValue [][]interface{}
			if allSingleChar(list) {
				keys := maps.Keys(data)
				for val := range keys {
					slist := strings.Split(val, ",")
					if len(slist) == len(list) {
						var snum = 0
						for i := 0; i < len(slist); i++ {
							if list[i][0] != slist[i][0] {
								break
							}
							snum++
						}
						if snum != len(slist) {
							continue
						}
						if len(data[val]) < num {
							retValue = append(retValue, data[val]...)
							continue
						}
						retValue = append(retValue, data[val]...)
					}
				}
			}
			return retValue
		}
		return
	}
	if len(data[pinyin]) < num {
		return data[pinyin]
	}
	return data[pinyin][:num]
}

func DagFunc(d *DagParams, PyList []string, PathNum int) []HeapItem {
	pyNum := len(PyList)
	if pyNum == 0 {
		return nil
	}
	var D []PrioritySet

	for range pyNum {
		D = append(D, PrioritySetInit(PathNum))
	}
	for i := range pyNum {
		kvs := d.GetPhrase(PyList[0:i+1], PathNum)
		for _, item := range kvs {
			var s = item[0].(string)
			var word []string
			word = append(word, s)
			score := item[1]

			D[i].Put(HeapItem{
				score: score.(float64),
				Path:  word,
			})
		}
	}

	for idx := 1; idx < pyNum; idx++ {
		prev_paths := D[idx-1]
		for to_idx := idx; to_idx < pyNum; to_idx++ {
			kvs := d.GetPhrase(PyList[idx:to_idx+1], PathNum)
			for prev_item := range prev_paths.Piter() {
				for _, item := range kvs {
					word := append(prev_item.Path, item[0].(string))
					score := prev_item.score * item[1].(float64)
					D[to_idx].Put(HeapItem{
						score: score,
						Path:  word,
					})
				}
			}
		}
	}
	//lastLen := len(D) - 1
	var hlist []HeapItem
	for i := range D {
		for item := range D[i].Piter() {
			hlist = append(hlist, item)
		}
	}
	//for item := range D[lastLen].Piter() {
	//	hlist = append(hlist, item)
	//}
	slices.SortFunc(hlist, func(a, b HeapItem) int {
		return cmp.Compare(b.score, a.score)
	})
	return hlist
}

func allSingleChar(arr []string) bool {
	for _, str := range arr {
		if len(str) != 1 {
			return false
		}
	}
	return true
}
